/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package View;

import Model.Intersection;
import Model.Traffic_Lights;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;

/**
 * Class that controls the drawing and construction of the intersection and cars.
 * @author Luke
 */
public class Gui_Intersection extends Intersection {

    private int block_width = 0; //variabel for block width
    private int block_height = 0; //variable for block height
    private int currentXPos = 0; //variable for the positionon the screen, used for block drawing
    private int currentYPos = 0; //as above
    private JFrame frame = new JFrame(); //instaintiate a new Frame, to be set later
    private Canvas canvas = new Canvas(); //as above
    private int blockCounter = 0; //a counter for number of blocks made per row
    private int blocksMade = 0; //counter for the number of total blocks made
    private Traffic_Lights lightControl = new Traffic_Lights(getNumVStreet()); //traffics lights are made

    /**
     * Constructor method for setting up the values used in the intersection.
     * @param streetValues The values passed into the Intersection from the user.
     * I.e the Number of lanes in the Horizontal street, probability etc.
     * @param frame The frame from the previous screen of the menu, passed through for re-use.
     */
    public Gui_Intersection(ArrayList<Number> streetValues, JFrame frame) {
        super(streetValues); //Street values is numlanes, probCars. Values passed in are set again in the parent class
        this.frame = frame; //the frame passed in is set the to fraem for this class
        frame.setLayout(new GridLayout(1, 1)); //give the frame a layout style
        setNumHStreet(streetValues.get(0).intValue()); //set the intersection specifics
        setNumVStreet(streetValues.get(1).intValue());
        setProbHCars(streetValues.get(2).floatValue());
        setProbVCars(streetValues.get(3).floatValue());
        generate_Lanes(10); //set the amount of filler wanted for the intersection
    }

    /**
     * Method used to reset the current canvas JPanel
     * @param aPanel The current canvas panel passed through from the previous menu screen.
     */
    public void resetCanvas(JPanel aPanel) {
        aPanel.removeAll(); //remove all components in the panel
        aPanel.validate(); //validate the panel
        aPanel.repaint(); //re draw the emptied panel
    }

    /**
     * The method used to start the thread that repaints the intersection.
     */
    public void initialise() {
        canvas = new Canvas();
        frame.add(canvas);
        calculateBlocks();
        //simulate();
        canvas.Painter.start();
    }


    /**
     * Method used to calculate the width and the height of the blocks drawn onto the intersection.
     */
    public void calculateBlocks() {
        int canvas_height = canvas.getSize().height; //get the canvas dimensions
        int canvas_width = canvas.getSize().width;
        block_width = canvas_width / getHorzArray().get(0).size(); //get the block dimensions
        block_height = (canvas_height / (getHorzArray().size() + (getN_filler() * 2)));
    }

    /**
     * The method that is called to make and move the cars through the intersection.
     * This method also controls the traffic light system.
     */
    public void simulate() {

        ArrayList newVCars = makeCars("vertical"); //make the vertical cars
        if (newVCars != null) {
            getVertArray().set(0, newVCars); //add the freshley generated cars to the vert array
        }

        ArrayList newHCars = makeCars("horizontal"); //make horizontal cars
        if (newHCars != null) {
            for (int i = 0; i < getHorzArray().size(); i++) {
                getHorzArray().get(i).set(0, newHCars.get(i)); //set cuurent nested array first element to current newCar
            }
        }

        //other thread should wake up here
        moveHCars(lightControl.getH_Lights()); //move cars
        moveVCars(lightControl.getV_Lights());
        lightControl.incrementCount();
        //System.out.println("VStreet-Lights: " + lightControl.getV_Lights()); add GUI functionality
        //System.out.println("HStreet-Lights: " + lightControl.getH_Lights());
    }

    /**
     * This method is a filter called from the paint component to determine which type of block to draw
     * @param g The graphics element passed in from the paint component
     * @param character A string passed in to filter the style of block desired to be drawn
     */
    public void selectBlockType(Graphics g, String character) {
        if (character.equals("-")) {
            for (int i = 0; i < getN_filler(); i++) { //for the amount fo filler
                makeBlock(g, Color.BLACK); //make black blocks
            }
        } else if (character.equals("blank")) {
            for (int i = 0; i < getN_filler(); i++) { //as above
                makeBlock(g, Color.WHITE);
            }
        } else if (character.equals("|")) { //for one time if this character is passed in
            makeBlock(g, Color.BLACK); //make this color block
        } else if (character.endsWith("r")) {
            makeBlock(g, Color.RED);
        } else if (character.endsWith("b")) {
            makeBlock(g, Color.BLUE);
        } else if (character.endsWith("y")) {
            makeBlock(g, Color.YELLOW);
        }else if (character.equals(" ")) {
            makeBlock(g, Color.darkGray);
        } else {
            System.out.println("Bad inpt" + character); //The character passed in was not compatible
        }
    }

    /**
     * This is the actual method that does all the block drawing for the intersection
     * @param g Graphics component passed from the select block method.
     * @param c The color object that is passed from the selectBlockType filtering method
     */
    public void makeBlock(Graphics g, Color c) {
        g.setColor(c); //sets the color
        g.fillRect(currentXPos, currentYPos, block_width, block_height); //make a filled rectangle
        g.setColor(Color.RED); //set color to red
        g.drawRect(currentXPos, currentYPos, block_width, block_height); //make a outline of a rectangle
        if (blockCounter == (getN_filler() * 2 + 1 + getNumVStreet())) { //if it is at the end of the columns
            currentXPos = 0; //back to the start of the columns
            currentYPos += block_height; //next row down
            blockCounter = 0; //reset the counter for the next row
        } else {
            currentXPos += block_width; //move block drawer one block space
            ++blockCounter; //increment the counter by 1

        }
    }

    /**
     *This method is called to draw the traffic lights onto the intersection
     * @param g Is the graphics object passed from the paint component
     */
    public void makeLights(Graphics g) {
        int hLight_x = ((getN_filler()) * block_width); //x position of the horizontal light
        int hLight_y = ((getN_filler() + getNumHStreet()) * block_height); //y position of the horizontal light
        int vLight_x = ((getN_filler() + getNumVStreet() + 1) * block_width); //as above
        int vLight_y = ((getN_filler() - 1) * block_height);

        if (lightControl.getH_Lights().equals("Green") && lightControl.getV_Lights().equals("Red")) { //horzitonal lights green and vertical red
            g.setColor(Color.GREEN);
            g.fillOval(hLight_x, hLight_y, block_width, block_height); //draw a green light
            g.setColor(Color.RED);
            g.fillOval(vLight_x, vLight_y, block_width, block_height); //draw a red light
        }  else if (lightControl.getH_Lights().equals("Red") && lightControl.getV_Lights().equals("Green")) { //swapped for above
            g.setColor(Color.RED);
            g.fillOval(hLight_x, hLight_y, block_width, block_height);
            g.setColor(Color.GREEN);
            g.fillOval(vLight_x, vLight_y, block_width, block_height);
        } else if (lightControl.getH_Lights().equals("Red") && lightControl.getV_Lights().equals("Red")) { //if both lights are red
            g.setColor(Color.RED);
            g.fillOval(hLight_x, hLight_y, block_width, block_height); //draw a red light
            g.setColor(Color.RED);
            g.fillOval(vLight_x, vLight_y, block_width, block_height); //draw a red light
        }
    }

    private class Canvas extends JPanel implements Runnable {

        private Thread Painter;

        public Canvas() {
            setVisible(true);
            setSize(frame.getSize().width, frame.getSize().height);
            Painter = new Thread(this, "Painter");
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);


            String filler = "blank"; //used for filling in the intersectiRed outline

            for (int i = 0; i < getVertArray().size(); i++) { //for loop for printing surround and first half of vertical intersection.

                if (i == (getN_filler() - 1)) { //when up to printing the 9th line
                    filler = "-"; //print dashes instead of filler
                } else if (i == getN_filler()) {
                    filler = "blank";
                    break; //if i reaches the amount of filler break the loop
                }

                selectBlockType(g, filler);
                selectBlockType(g, "|");
                for (int j = 0; j < getVertArray().get(i).size(); j++) { //display the horizontal gap
                    selectBlockType(g, getVertArray().get(i).get(j).toString()); //prints current index of nested array
                }
                selectBlockType(g, "|");
                selectBlockType(g, filler);
            }
            for (int i = 0; i < getHorzArray().size(); i++) { //for loops in for loops used for outputing horzontal ArrayList
                for (int j = 0; j < getHorzArray().get(i).size(); j++) {
                    selectBlockType(g, getHorzArray().get(i).get(j).toString());
                }
            }

            for (int i = 0; i < getVertArray().size(); i++) { //for loop that controls printing the surrounds and second half of the vertical intersection
                if (i == 0) {
                    filler = "-";
                } else if (i == getN_filler()) {
                    filler = "blank";
                    break; //if i reaches the amount of n_filler break the loop
                } else {
                    filler = "blank";
                }
                ArrayList temp = (ArrayList) getVertArray().get(i + getN_filler()); //make an alias for nested referencing and increase index by 10
                selectBlockType(g, filler);
                selectBlockType(g, "|");
                for (int j = 0; j < temp.size(); j++) { //display the horizontal gap
                    selectBlockType(g, temp.get(j).toString()); //prints current index of nested array
                }
                selectBlockType(g, "|");
                selectBlockType(g, filler);
            }

            currentYPos = 0; //reset the position of the blocks to be drawn for the next time the thread gets priority
            currentXPos = 0;
            makeLights(g); //call the method to draw the lights
        }

       

        public void run() {

            while (true) {
                try {
                    Thread.sleep(500);
                    repaint(); //call the paint component
                    simulate(); //call the method to move and make cars + lights
                } catch (Exception e) {
                    System.out.println(e);
                }
            }
        }
    }
}
